<?php

namespace app\common\traits;

use yiqiniu\extend\facade\Extend;

trait ApiInterfaceTrait
{
    /**
     * 接口列表
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getActions()
    {
        return $this->db()->order('sort desc')
            ->where('auth', '>' , 0)
            ->field('id,pid,title,type_id,page_action')->select();
//            ->where('type_id', 2)
//            ->whereOr(function ($query) {
//                $query->where('type_id', '<', 2)->where('pid', '>', 0)->where('title', '>', '')->where('auth','>',0);
//            })

    }


    /**
     * json转到 保存到表中
     * @param array $jsonRoute
     * @param string $module
     * @return int
     * @throws \think\Exception
     */
    public function jsonSaveToTable(array $jsonRoute, string $module = ''): int
    {
        $map['page_action'] = ['<>', ''];
        $map['type_id'] = ['<', 2];
        if (!empty($module)) {
            $map['module'] = ['=', $module];
        }

        // 获取route_path 不为空地址
        $list = $this->where($map)
            ->field('id,title,router_method,page_action,pid,auth,type_id')
            ->select();

        $list = Extend::Arrays()->toTree($list, 'id', 'pid', 'rules');

        $updateData = $diffData = [];
        $dbRoute = array_column($list, null, 'page_action');
        $jsonRoute = array_column($jsonRoute, null, 'rule');
        $diffRoute = array_diff(array_keys($dbRoute), array_keys($jsonRoute));
        foreach ($diffRoute as $path) {
            if (isset($dbRoute[$path])) {
                $diffData[] = $dbRoute[$path]['id'];
                if (!empty($dbRoute[$path]['rules'])) {
                    $diffData = array_merge($diffData, array_column($dbRoute[$path]['rules'], 'id'));
                }
            }
        }
        $now = date('Y-m-d H:i:s');
        $addUpdateFun = function ($id, &$item) use (&$updateData, $now) {
            $updateData[$id] = [
                'title' => $item['title'],
                'router_method' => $item['method'] ?? 'get',
                'page_action' => $item['rule'],
                'auth' => $item['auth'] ?? 2,
                'update_at' => $now
            ];
        };
        foreach ($jsonRoute as $rule => $row) {
            $insertData = [];
            // 插入不存在的一级信息
            if (!isset($dbRoute[$rule])) {
                $this->insertRoute($row, 0, $module);
                continue;
            }

            // 添加到更新队列
            $addUpdateFun($dbRoute[$rule]['id'], $row);
            if (!empty($row['rules'])) {
                $jsonAction = array_column($row['rules'], null, 'rule');
                $dbAction = array_column($dbRoute[$rule]['rules'], null, 'page_action');
                foreach ($jsonAction as $act => $item) {
                    if (isset($dbAction[$act])) {
                        $addUpdateFun($dbAction[$act]['id'], $item);
                    } else {
                        $insertData[] = $item;
                    }
                }
                $diffRoute = array_diff(array_keys($dbAction), array_keys($jsonAction));
                foreach ($diffRoute as $path) {
                    if (isset($dbAction[$path])) {
                        $diffData[] = $dbAction[$path]['id'];
                    }
                }
                if (!empty($insertData)) {
                    $this->insertRoute($insertData, $dbRoute[$rule]['id'], $module);
                }
            }
        }


        if (!empty($updateData)) {
            $db = $this->db();
            foreach ($updateData as $id => $data) {
                $db->removeOption()->where('id', $id)->update($data);
            }
        }
        if (!empty($diffData)) {
            $this->removeOption()->whereIn('id', $diffData)->where('type_id', '<', 2)->delete();
        }
        $where['pid'] = ['>', 0];
        $child_count = $this->removeOption()->where($where)->group('pid')->column([], 'count(id) as child,SUM(case when title=\'\' then 1 else 0 end) as untitled_child,SUM(case when auth=2 then 1 else 0 end) as role_auth_child,SUM(case when auth=1 then 1 else 0 end) as login_auth_child,SUM(case when auth=0 then 1 else 0 end) as anonymous_auth_child', 'pid');
        foreach ($child_count as $pid => $child) {
            $this->removeOption()->where('id', $pid)->update([], [
                'child' => $child['child'] ?? 0,
                'untitled_child' => $child['untitled_child'] ?? 0,
                'role_auth_child' => $child['role_auth_child'] ?? 0,
                'login_auth_child' => $child['login_auth_child'] ?? 0,
                'anonymous_auth_child' => $child['anonymous_auth_child'] ?? 0
            ]);
        }
        return 1;
    }

    /**
     * 插入一个操作的操作下的所有方法
     * @param array $jsonData
     * @param int $pid
     * @param string $module
     * @return void
     */
    private function insertRoute(array $jsonData, int $pid = 0, string $module = ''): int
    {
        $now = date('Y-m-d H:i:s');
        if ($pid === 0) {
            $insetData = [
                'title' => $jsonData['title'],
                'router_method' => $jsonData['method'] ?? 'get',
                'page_action' => $jsonData['rule'],
                'pid' => 0,
                'group_id' => 0,
                'auth' => $jsonData['auth'] ?? 2,
                'type_id' => 1,
                'update_at' => $now,
                'module' => $module
            ];
            $pid = $this->db()->insertGetId($insetData);
            $jsonData = $jsonData['rules'];
        }

        if ($pid > 0) {
            $insetData = [];
            foreach ($jsonData as $rule) {
                $insetData[] = [
                    'title' => $rule['title'],
                    'router_method' => $rule['method'],
                    'page_action' => $rule['rule'],
                    'pid' => $pid,
                    'group_id' => 0,
                    'auth' => $rule['auth'],
                    'update_at' => $now,
                    'module' => $module
                ];
            }
            if (!empty($insetData)) {
                $this->db()->insertAll($insetData);
            }
        }
        return $pid;
    }

}
